<template>
  <div class="wy-tree-container">
    <Tree
      ref="wy-tree"
      :data="treeData"
      :show-checkbox="config.showCheckbox"
      :isAllCheck="isAllCheck"
      @on-contextmenu="onContextmenu"
      @on-select-change="onSelectChange"
      @on-check-change="onCheckChange"
      @on-toggle-expand="onToggleExpand"
    >
      <template slot="contextMenu">
        <slot name="treeContextMenu"></slot>
      </template>
    </Tree>
  </div>
</template>

<script lang="ts">
import { Tsrv, T_srv, vue } from '@/services';
import { N_oTree } from './types';

@T_srv.comp({})
export default class oTree extends vue {
  // modify by wiz
  public compName: string = 'oTree';

  @T_srv.prop() config!: N_oTree.I_conf;

  @T_srv.prop({ default: false }) isAllCheck: Boolean;

  @T_srv.ref('tree') tree;

  private wyTree: any = null;

  get treeData() {
    const datas: any = this.formatTreeData(
      this.toArrayTree(this.TreeDatas.data)
    );
    datas.forEach(el => {
      const circle = Tsrv.utils.some<any>(
        el.children,
        item => item.data.circle === 1
      );

      circle && (el.data.circle = 1);
    });

    return datas;
  }

  get TreeDatas() {
    return this.config;
  }

  // 点击树节点时触发
  @T_srv.emit()
  public onSelectChange(e) {}

  // 点击复选框时触发
  @T_srv.emit()
  public onCheckChange(e) {}

  // 展开和收起子列表时触发
  @T_srv.emit()
  public onToggleExpand(e) {}

  // 展开和收起子列表时触发
  @T_srv.emit()
  public onContextmenu(datas) {}

  // 获取被勾选的节点
  public getCheckedNodes() {
    return this.tree.getCheckedNodes();
  }

  // 获取被选中的节点
  public getSelectedNodes() {
    return this.tree.getSelectedNodes();
  }

  // 获取选中及半选节点
  public getCheckedAndIndeterminateNodes() {
    return this.tree.getCheckedAndIndeterminateNodes();
  }

  // 带父节点数据转树数组
  public toArrayTree(d: Array<N_oTree.I_data>) {
    return Tsrv.utils.toArrayTree(d, {
      // 默认数据入在data对象中
      data: 'data',
      // 行ID 字段
      key: this.config.keyName || 'id',
      // 父ID字段名
      parentKey: this.config.parentKeyName || 'parentId'
    });
  }

  //  自定义Tree内容
  public formatTreeData(d: any) {
    d.forEach(item => {
      item.render = this.renderContent; // 渲染

      item.data['expand'] && (item.expand = !!item.data.expand);
      item.data['selected'] && (item.selected = !!item.data.selected);
      item.data['checked'] && (item.checked = !!item.data.checked);
      item.data['contextmenu'] && (item.contextmenu = !!item.data.contextmenu);

      this.config.nodeIcon && (item.nodeIcon = this.config.nodeIcon);
      this.config.leafIcon && (item.leafIcon = this.config.leafIcon);
      item['children'] && (item.children = this.formatTreeData(item.children));
    });
    return d;
  }

  // eslint-disable-next-line no-shadow
  public renderContent(h: any, { root, node, data }) {
    // iView 树渲染内容，详见https://www.iviewui.com/components/tree
    return h(
      'span',
      {
        style: {
          display: 'inline-block',
          width: '100%'
        }
      },
      [
        h('span', { class: 'tree-item' }, [
          h('Icon', {
            props: {
              type: data.data.isNode // 节点标识
                ? data.nodeIcon || 'ios-folder-outline' // 节点图标
                : data.leafIcon || 'ios-document-outline' // 叶子内容图标
            },
            style: {
              marginRight: '8px'
            }
          }),
          h(
            'span',
            { class: 'tree-title', attrs: { title: data.data.title } },
            data.data.title
          ), // 节点标题
          data.data.circle === 1 && h('b', { class: 'tree-circle' })
        ])
      ]
    );
  }

  public appendTreeNode(datas: any) {
    const children = datas.children || [];
    children.push({
      title: 'appended node',
      expand: true
    });
    this.$set(datas, 'children', children);
  }

  public removeTreeNode(root, node, datas) {
    const parentKey = root.find(el => el === node).parent;
    const parent = root.find(el => el.nodeKey === parentKey).node;
    const index = parent.children.indexOf(datas);
    parent.children.splice(index, 1);
  }

  // 全选切换
  public toggleAllCheck() {
    let arr: any = [];

    if (this.isAllCheck) {
      this.TreeDatas.data.forEach(el => {
        el.checked = 0;
      });
      arr = [];
    } else {
      this.TreeDatas.data.forEach(el => {
        el.checked = 1;
      });
      this.treeData.forEach(el => {
        arr.push(el);
        arr.push(...el.children);
      });
    }

    this.$emit('on-check-change', arr);
  }
}
</script>

<style lang="scss" scoped>
$circleLong: 5px;
$top: calc(-1 * $circleLong / 2);
.wy-tree-container {
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
  ::v-deep.tree-item {
    position: relative;
    ::v-deep.tree-circle {
      position: absolute;
      top: $top;
      left: 12px;
      width: $circleLong;
      height: $circleLong;
      display: block;
      background-color: #fb4242;
      border-radius: 50%;
    }
  }
}
</style>
